//
// server.hpp
// ~~~~~~~~~~
//

#ifndef HTTP_SERVER2_SERVER_HPP
#define HTTP_SERVER2_SERVER_HPP

#include <boost/asio.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include "connection.hpp"
#include "io_service_pool.hpp"
#include "lru_cache_using_boost.hpp"
#include <map>

namespace http {
    namespace server3 {

        /// The top-level class of the HTTP server.
        class server
            : private boost::noncopyable
        {
        public:
            /// Construct the server to listen on the specified TCP address and port, and
            /// serve up files from the given directory.
            explicit server(const std::string& address, const std::string& port, std::size_t io_service_pool_size);

            /// Run the server's io_service loop.
            void run();
            void initialize_log();
            // Get current date/time, format is YYYY-MM-DD.HH:mm:ss
            static std::string currentDateTime();
            static std::map<std::string, int> business_count_map;
            static boost::mutex map_mutex;
            static int request_rate;
            static long cache_hit;
            static long cache_miss;
            static long received_zc1;
            static long parsing_error;
            static long processed_zc1;
            static std::string log_time;

            static void log_business_count_impl(std::string bsn_name){
            	std::map<std::string,int>::iterator it;
            	typedef std::pair<std::string, int> map_pair;
            	it = server::business_count_map.find(bsn_name);
            	if (it == server::business_count_map.end()){
            		server::map_mutex.lock();
            		server::business_count_map.insert(map_pair(bsn_name,1));
            		server::map_mutex.unlock();
            	}else{
            		__sync_fetch_and_add(&it->second,1);
            	}
            }
            static int log_get_business_count_impl(std::string bsn_name){
            	std::map<std::string,int>::iterator it;
            	typedef std::pair<std::string, int> map_pair;
            	it = server::business_count_map.find(bsn_name);
            	if (it == server::business_count_map.end()){
            		return -1;
            	}else{
                    return it->second;
            	}
            }

            static bool log_reset_business_count_impl(std::string bsn_name){
            	std::map<std::string,int>::iterator it;
            	typedef std::pair<std::string, int> map_pair;
            	it = server::business_count_map.find(bsn_name);
            	if (it == server::business_count_map.end()){
            		return false;
            	}else{
                    it->second = 0;
                    return true;
            	}
            }


            //added by KhanhHH
            //storing caching data
            typedef lru_cache_using_boost<std::string, std::string> lru_cache;
            static boost::shared_ptr<lru_cache> mobile_cache_ptr_;
            std::string static start_time;
            int static unknown_ip;
            int static cache_size;
            int static total_request;
            int static error_request;

        private:
            /// Initiate an asynchronous accept operation.
            void start_accept();

            /// Handle completion of an asynchronous accept operation.
            void handle_accept(const boost::system::error_code& e);

            /// Handle a request to stop the server.
            void handle_stop();

            //Called by timer for calculate rate.
            void calculate_rate();

            /// The pool of io_service objects used to perform asynchronous operations.
            io_service_pool io_service_pool_;

            /// The signal_set is used to register for process termination notifications.
            boost::asio::signal_set signals_;

            /// Acceptor used to listen for incoming connections.
            boost::asio::ip::tcp::acceptor acceptor_;

            /// The next connection to be accepted.
            connection_ptr new_connection_;

            /// timer for ending connection after timeout.
            boost::asio::deadline_timer rate_timer_;
            int last_request_num;
            int refresh_rate_timeout;

        };

    } // namespace server2
} // namespace http

#endif // HTTP_SERVER2_SERVER_HPP
